#include "ff_gen_drv.h"
#include "usbh_diskio.h"
#include "usbh_msc_scsi.h"
#include "usbh_msc_bot.h"

extern USB_OTG_CORE_HANDLE  USB_OTG_Core;
extern USBH_HOST  USB_Host;

/* Private function prototypes -----------------------------------------------*/
DSTATUS USBH_initialize (BYTE);
DSTATUS USBH_status (BYTE);
DRESULT USBH_read (BYTE, BYTE*, DWORD, UINT);

#if _USE_WRITE == 1
  DRESULT USBH_write (BYTE, const BYTE*, DWORD, UINT);
#endif /* _USE_WRITE == 1 */

#if _USE_IOCTL == 1
  DRESULT USBH_ioctl (BYTE, BYTE, void*);
#endif /* _USE_IOCTL == 1 */

const Diskio_drvTypeDef  USBH_Driver =
{
  USBH_initialize,
  USBH_status,
  USBH_read,
#if  _USE_WRITE == 1
  USBH_write,
#endif /* _USE_WRITE == 1 */
#if  _USE_IOCTL == 1
  USBH_ioctl,
#endif /* _USE_IOCTL == 1 */
};


/* Private functions ---------------------------------------------------------*/

/**
  * @brief  Initializes a Drive
  * @param  lun : lun id
  * @retval DSTATUS: Operation status
  */
DSTATUS USBH_initialize(BYTE lun)
{
  /* CAUTION : USB Host library has to be initialized in the application */
  DRESULT res = RES_ERROR;

 if(HCD_IsDeviceConnected(&USB_OTG_Core))
 {
   res = RES_OK;
 }
 else
 {
   res = RES_ERROR;
 }


  return res;
}



/**
  * @brief  Gets Disk Status
  * @param  lun : lun id
  * @retval DSTATUS: Operation status
  */
DSTATUS USBH_status(BYTE lun)
{
  DRESULT res = RES_ERROR;
	res = RES_OK;
  return res;
}


/**
  * @brief  Reads Sector(s)
  * @param  lun : lun id
  * @param  *buff: Data buffer to store read data
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to read (1..128)
  * @retval DRESULT: Operation result
  */
DRESULT USBH_read(BYTE lun, BYTE *buff, DWORD sector, UINT count)
{
    DRESULT res = RES_ERROR;
    BYTE status = USBH_MSC_OK;

    //if (Stat & STA_NOINIT) 	return RES_NOTRDY;

    if (HCD_IsDeviceConnected(&USB_OTG_Core))
    {
      do
      {
        status = USBH_MSC_Read10(&USB_OTG_Core, buff,sector,512 * count);
        USBH_MSC_HandleBOTXfer(&USB_OTG_Core ,&USB_Host);

        if (!HCD_IsDeviceConnected(&USB_OTG_Core))
        {
          break;
        }
      }
      while (status == USBH_MSC_BUSY );
    }

    if (status == USBH_MSC_OK)
    {
      res = RES_OK;
    }
    else
    {
      res = RES_ERROR;
    }
    return res;
}



/**
  * @brief  Writes Sector(s)
  * @param  lun : lun id
  * @param  *buff: Data to be written
  * @param  sector: Sector address (LBA)
  * @param  count: Number of sectors to write (1..128)
  * @retval DRESULT: Operation result
  */
#if _USE_WRITE == 1
DRESULT USBH_write(BYTE lun, const BYTE *buff, DWORD sector, UINT count)
{
    DRESULT res = RES_ERROR;
    BYTE status = USBH_MSC_OK;
    if (HCD_IsDeviceConnected(&USB_OTG_Core))
    {
      do
      {
        status = USBH_MSC_Write10(&USB_OTG_Core,(BYTE*)buff,sector, 512 * count);
        USBH_MSC_HandleBOTXfer(&USB_OTG_Core, &USB_Host);

        if(!HCD_IsDeviceConnected(&USB_OTG_Core))
        {
          break;
        }
      }
      while(status == USBH_MSC_BUSY );

    }

    if (status == USBH_MSC_OK)
    {
      res = RES_OK;
    }
    else
    {
      res = RES_ERROR;
    }
    return res;
}
#endif /* _USE_WRITE == 1 */

/**
  * @brief  I/O control operation
  * @param  lun : lun id
  * @param  cmd: Control code
  * @param  *buff: Buffer to send/receive control data
  * @retval DRESULT: Operation result
  */
#if _USE_IOCTL == 1
DRESULT USBH_ioctl(BYTE lun, BYTE cmd, void *buff)
{
    DRESULT res = RES_ERROR;

    switch (cmd)
    {
        /* Make sure that no pending write process */
        case CTRL_SYNC:
            res = RES_OK;
            break;
        /* Get number of sectors on the disk (DWORD) */
        case GET_SECTOR_COUNT :
            *(DWORD*)buff=USBH_MSC_Param.MSCapacity;
            res = RES_OK;
            break;
        /* Get R/W sector size (WORD) */
        case GET_SECTOR_SIZE :
            *(WORD*)buff=512;
            res = RES_OK;
            break;
          /* Get erase block size in unit of sector (DWORD) */
        case GET_BLOCK_SIZE :
            *(WORD*)buff=512;
            res = RES_OK;
            break;
        default:
          res = RES_PARERR;
    }
    return res;
}
#endif /* _USE_IOCTL == 1 */

/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/


